/* Scraper.h
Copyright (c) 2008 Michael Zahniser
Please note the license terms (MIT license) at the end of this document.

Header file for the Scraper abstract base class, the interface for a web-scraping
object that can retrieve a set of images ordered by some sequence number.
*/

#ifndef __MZ_SCRAPER_H__
#define __MZ_SCRAPER_H__

#include "_web/Curl.h"

#include <string>
#include <ctime>
#include <istream>
#include <ostream>

using std::string;
using std::tm;
using std::istream;
using std::ostream;



class Scraper {
public:
	// Constructor and destructor.
	Scraper();
	virtual ~Scraper() {}
	
	// Make a copy of this Scraper.
	Scraper *Clone() const;
	
	// Go to the previous, next, or last item in the sequence and load it into
	// the given buffer, using the given internet connection.
	bool Previous(string &buffer, Curl &curl);
	bool Next(string &buffer, Curl &curl);
	bool Last(string &buffer, Curl &curl);
	bool Reload(string &buffer, Curl &curl);
	
	// Get the description of the current item.
	string Description() const;
	
	// Write this scraper's state to the given output file, or read it from the
	// given input file.
	void Load(istream &in);
	void Save(ostream &out) const;
	
	// Get the image type.
	const string &ImageType() const { return imageType; }
	
	
protected:
	// These functions should be overridden by derived classes to specify the
	// behavior of the Scraper.
	
	// Make a copy of this Scraper.
	virtual Scraper *DoClone() const = 0;
	
	// Get the greatest valid index.
	virtual int GetLastIndex() const = 0;
	// Get the path to load the image from.
	// If the path cannot simply be guessed from the index, override LoadIndex
	// instead.
	virtual string GetPath(int index) const = 0;
	// Get the description of the current image.
	virtual string GetDescription(int index) const = 0;
	
	// This function is for derived classes to report their initial indices.
	void SetIndex(int index);
	// Convert a time into a string.
	static string DateToString(const tm &date);
	
	// Load the comic with the given index into the given buffer, using the
	// given internet connection.
	virtual bool LoadIndex(int index, string &buffer, Curl &curl);
	
	// Fetch the contents of the given path into the given buffer.
	// If the fetch fails, the buffer will be empty.
	void Fetch(const string &path, string &buffer, Curl &curl);
	
	// Set the referer website. This function is const to allow it to be called
	// from GetPath(). It's probably a good idea to set the referer to the full path
	// to a page that actually contains a given comic.
	void SetReferer(const string &referer) const;
	
	
private:
	// Perform some of the more obvious checks to see if image download failed.
	static bool IsNotAnImage(const string &buffer);


private:
	// We are at this index, currently.
	int currentIndex;
	// This is the extension of the image ("png", "gif", or "jpg").
	string imageType;
	// Derived classes can set this in order to send a referer header.
	mutable string referer;
};



#endif

/* Copyright (c) 2008 Michael Zahniser

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. */
